#include "class_parser.hpp"
#include <fstream>
#include <streambuf>
#include <sys/stat.h>

class Mybuf : public std::streambuf {
protected:
	char *buf;
	char *cur_ptr;
	int length;
public:
	Mybuf(char *buf, int length) : buf(buf), length(length) {
		setg(buf, buf, buf + length);
	}
};

// 一个字节码拦截器：内部工具。只有在对 class_parser.hpp/cpp 编译的时候加上 POOL_DEBUG 宏编译的时候，才有输出结果。否则不会输出。
// 这个字节码工具可以用于 VM Anonymous Class 的调试工具。使用方法：在 MyClassLoader 的代码处，可以看到几处拦截区域。获取到 VM Anonymous Class 的 name
// 之后，把 name 写入到拦截区域，那么在跑 vm 的时候，拦截区域截取到指定的 VM Anonymous Class 之后，会输出16进制字节码。如下所示。直接 copy + paste 过来，
// 即可查看字节码的内部结构。
// jdk 内部 lambda 部分很多 ClassFile 全是通过注入来实现的。这样可以很方便，比如使用一次即卸载，也可以完全隐藏实现。
// 此 tool 就是抱着这样的目的而产生。把 class_parser.cpp 带上 POOL_DEBUG 宏编译，运行之后，下边的字节码就被解析为 ClassFile 如下：
/**

(DEBUG) cafebabe 0 52 49
(DEBUG) constpool_size: 49
(DEBUG) #   1 = Utf8                  Test13$$Lambda$1
(DEBUG) #   2 = Class                 #1
(DEBUG) #   3 = Utf8                  java/lang/Object
(DEBUG) #   4 = Class                 #3
(DEBUG) #   5 = Utf8                  JJ
(DEBUG) #   6 = Class                 #5
(DEBUG) #   7 = Utf8                  arg$1
(DEBUG) #   8 = Utf8                  LCC;
(DEBUG) #   9 = Utf8                  <init>
(DEBUG) #  10 = Utf8                  (LCC;)V
(DEBUG) #  11 = Utf8                  ()V
(DEBUG) #  12 = NameAndType           #9.#11
(DEBUG) #  13 = Methodref             #4.#12
(DEBUG) #  14 = NameAndType           #7.#8
(DEBUG) #  15 = Fieldref              #2.#14
(DEBUG) #  16 = Utf8                  get$Lambda
(DEBUG) #  17 = Utf8                  (LCC;)LJJ;
(DEBUG) #  18 = NameAndType           #9.#10
(DEBUG) #  19 = Methodref             #2.#18
(DEBUG) #  20 = Utf8                  foo
(DEBUG) #  21 = Utf8                  (Ljava/lang/Object;)Ljava/lang/Object;
(DEBUG) #  22 = Utf8                  Ljava/lang/invoke/LambdaForm$Hidden;
(DEBUG) #  23 = Utf8                  java/lang/Integer
(DEBUG) #  24 = Class                 #23
(DEBUG) #  25 = Utf8                  intValue
(DEBUG) #  26 = Utf8                  ()I
(DEBUG) #  27 = NameAndType           #25.#26
(DEBUG) #  28 = Methodref             #24.#27
(DEBUG) #  29 = Utf8                  CC
(DEBUG) #  30 = Class                 #29
(DEBUG) #  31 = Utf8                  impl
(DEBUG) #  32 = Utf8                  (I)Ljava/lang/String;
(DEBUG) #  33 = NameAndType           #31.#32
(DEBUG) #  34 = Methodref             #30.#33
(DEBUG) #  35 = Utf8                  writeObject
(DEBUG) #  36 = Utf8                  (Ljava/io/ObjectOutputStream;)V
(DEBUG) #  37 = Utf8                  java/io/NotSerializableException
(DEBUG) #  38 = Class                 #37
(DEBUG) #  39 = Utf8                  Non-serializable lambda
(DEBUG) #  40 = String                #39
(DEBUG) #  41 = Utf8                  (Ljava/lang/String;)V
(DEBUG) #  42 = NameAndType           #9.#41
(DEBUG) #  43 = Methodref             #38.#42
(DEBUG) #  44 = Utf8                  readObject
(DEBUG) #  45 = Utf8                  (Ljava/io/ObjectInputStream;)V
(DEBUG) #  46 = Utf8                  Code
(DEBUG) #  47 = Utf8                  RuntimeVisibleAnnotations
(DEBUG) #  48 = Utf8                  Exceptions
(DEBUG) ----------------- (Test13$$Lambda$1) static constant_pool over --------------------
(DEBUG) access_flags: 4144  this_class: #2  super_class: #4
(DEBUG) Interfaces: 6 
(DEBUG) field_info_size: 1
(DEBUG) private final arg$1;
(DEBUG)   descriptor: LCC;
(DEBUG)   flags: ACC_PRIVATE, ACC_FINAL
(DEBUG) method_number: 5
(DEBUG)
(DEBUG) private <init>;
(DEBUG)   descriptor: (LCC;)V
(DEBUG)   flags: ACC_PRIVATE
(DEBUG)   Code: 
(DEBUG)     stack=256, locals=2
(DEBUG)       0: aload_0        
(DEBUG)       1: invokespecial   #13
(DEBUG)       4: aload_0        
(DEBUG)       5: aload_1        
(DEBUG)       6: putfield       
(DEBUG)       9: return         
(DEBUG)
(DEBUG) private static get$Lambda;
(DEBUG)   descriptor: (LCC;)LJJ;
(DEBUG)   flags: ACC_PRIVATE, ACC_STATIC
(DEBUG)   Code: 
(DEBUG)     stack=3, locals=1
(DEBUG)       0: new             #2
(DEBUG)       3: dup            
(DEBUG)       4: aload_0        
(DEBUG)       5: invokespecial   #19
(DEBUG)       8: areturn        
(DEBUG)
(DEBUG) public foo;
(DEBUG)   descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
(DEBUG)   flags: ACC_PUBLIC
(DEBUG)   Code: 
(DEBUG)     stack=2, locals=2
(DEBUG)       0: aload_0        
(DEBUG)       1: getfield       
(DEBUG)       4: aload_1        
(DEBUG)       5: checkcast      
(DEBUG)       8: invokevirtual   #28
(DEBUG)      11: invokevirtual   #34
(DEBUG)      14: areturn        
(DEBUG)   RuntimeVisibleAnnotations:
(DEBUG)     0: #22()
(DEBUG)
(DEBUG) private final  throws java/io/NotSerializableException writeObject;
(DEBUG)   descriptor: (Ljava/io/ObjectOutputStream;)V
(DEBUG)   flags: ACC_PRIVATE, ACC_FINAL
(DEBUG)   Code: 
(DEBUG)     stack=3, locals=2
(DEBUG)       0: new             #38
(DEBUG)       3: dup            
(DEBUG)       4: ldc            
(DEBUG)       6: invokespecial   #43
(DEBUG)       9: athrow         
(DEBUG)   Exceptions: 
(DEBUG)     throws java/io/NotSerializableException 
(DEBUG)
(DEBUG)
(DEBUG) private final  throws java/io/NotSerializableException readObject;
(DEBUG)   descriptor: (Ljava/io/ObjectInputStream;)V
(DEBUG)   flags: ACC_PRIVATE, ACC_FINAL
(DEBUG)   Code: 
(DEBUG)     stack=3, locals=2
(DEBUG)       0: new             #38
(DEBUG)       3: dup            
(DEBUG)       4: ldc            
(DEBUG)       6: invokespecial   #43
(DEBUG)       9: athrow         
(DEBUG)   Exceptions: 
(DEBUG)     throws java/io/NotSerializableException 
(DEBUG)
(DEBUG)
(DEBUG) no class attributes.


*/

int main(int argc, char *argv[]) 
{
	
	std::wcout.imbue(std::locale(""));
	
//	struct stat64 stat;
//	assert(stat64("/Users/zhengxiaolin/Documents/java/java_class_parser/Example.class", &stat) != -1);
//	char *the_buf = new char[stat.st_size];
	
	unsigned char the_buf[] = {0xca,0xfe,0xba,0xbe,0,0,0,0x34,0,0x31,0x1,0,0x10,0x54,0x65,0x73,0x74,0x31,0x33,0x24,0x24,0x4c,0x61,0x6d,0x62,0x64,0x61,0x24,0x31,0x7,0,0x1,0x1,0,0x10,0x6a,0x61,0x76,0x61,0x2f,0x6c,0x61,0x6e,0x67,0x2f,0x4f,0x62,0x6a,0x65,0x63,0x74,0x7,0,0x3,0x1,0,0x2,0x4a,0x4a,0x7,0,0x5,0x1,0,0x5,0x61,0x72,0x67,0x24,0x31,0x1,0,0x4,0x4c,0x43,0x43,0x3b,0x1,0,0x6,0x3c,0x69,0x6e,0x69,0x74,0x3e,0x1,0,0x7,0x28,0x4c,0x43,0x43,0x3b,0x29,0x56,0x1,0,0x3,0x28,0x29,0x56,0xc,0,0x9,0,0xb,0xa,0,0x4,0,0xc,0xc,0,0x7,0,0x8,0x9,0,0x2,0,0xe,0x1,0,0xa,0x67,0x65,0x74,0x24,0x4c,0x61,0x6d,0x62,0x64,0x61,0x1,0,0xa,0x28,0x4c,0x43,0x43,0x3b,0x29,0x4c,0x4a,0x4a,0x3b,0xc,0,0x9,0,0xa,0xa,0,0x2,0,0x12,0x1,0,0x3,0x66,0x6f,0x6f,0x1,0,0x26,0x28,0x4c,0x6a,0x61,0x76,0x61,0x2f,0x6c,0x61,0x6e,0x67,0x2f,0x4f,0x62,0x6a,0x65,0x63,0x74,0x3b,0x29,0x4c,0x6a,0x61,0x76,0x61,0x2f,0x6c,0x61,0x6e,0x67,0x2f,0x4f,0x62,0x6a,0x65,0x63,0x74,0x3b,0x1,0,0x24,0x4c,0x6a,0x61,0x76,0x61,0x2f,0x6c,0x61,0x6e,0x67,0x2f,0x69,0x6e,0x76,0x6f,0x6b,0x65,0x2f,0x4c,0x61,0x6d,0x62,0x64,0x61,0x46,0x6f,0x72,0x6d,0x24,0x48,0x69,0x64,0x64,0x65,0x6e,0x3b,0x1,0,0x11,0x6a,0x61,0x76,0x61,0x2f,0x6c,0x61,0x6e,0x67,0x2f,0x49,0x6e,0x74,0x65,0x67,0x65,0x72,0x7,0,0x17,0x1,0,0x8,0x69,0x6e,0x74,0x56,0x61,0x6c,0x75,0x65,0x1,0,0x3,0x28,0x29,0x49,0xc,0,0x19,0,0x1a,0xa,0,0x18,0,0x1b,0x1,0,0x2,0x43,0x43,0x7,0,0x1d,0x1,0,0x4,0x69,0x6d,0x70,0x6c,0x1,0,0x15,0x28,0x49,0x29,0x4c,0x6a,0x61,0x76,0x61,0x2f,0x6c,0x61,0x6e,0x67,0x2f,0x53,0x74,0x72,0x69,0x6e,0x67,0x3b,0xc,0,0x1f,0,0x20,0xa,0,0x1e,0,0x21,0x1,0,0xb,0x77,0x72,0x69,0x74,0x65,0x4f,0x62,0x6a,0x65,0x63,0x74,0x1,0,0x1f,0x28,0x4c,0x6a,0x61,0x76,0x61,0x2f,0x69,0x6f,0x2f,0x4f,0x62,0x6a,0x65,0x63,0x74,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x3b,0x29,0x56,0x1,0,0x20,0x6a,0x61,0x76,0x61,0x2f,0x69,0x6f,0x2f,0x4e,0x6f,0x74,0x53,0x65,0x72,0x69,0x61,0x6c,0x69,0x7a,0x61,0x62,0x6c,0x65,0x45,0x78,0x63,0x65,0x70,0x74,0x69,0x6f,0x6e,0x7,0,0x25,0x1,0,0x17,0x4e,0x6f,0x6e,0x2d,0x73,0x65,0x72,0x69,0x61,0x6c,0x69,0x7a,0x61,0x62,0x6c,0x65,0x20,0x6c,0x61,0x6d,0x62,0x64,0x61,0x8,0,0x27,0x1,0,0x15,0x28,0x4c,0x6a,0x61,0x76,0x61,0x2f,0x6c,0x61,0x6e,0x67,0x2f,0x53,0x74,0x72,0x69,0x6e,0x67,0x3b,0x29,0x56,0xc,0,0x9,0,0x29,0xa,0,0x26,0,0x2a,0x1,0,0xa,0x72,0x65,0x61,0x64,0x4f,0x62,0x6a,0x65,0x63,0x74,0x1,0,0x1e,0x28,0x4c,0x6a,0x61,0x76,0x61,0x2f,0x69,0x6f,0x2f,0x4f,0x62,0x6a,0x65,0x63,0x74,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x3b,0x29,0x56,0x1,0,0x4,0x43,0x6f,0x64,0x65,0x1,0,0x19,0x52,0x75,0x6e,0x74,0x69,0x6d,0x65,0x56,0x69,0x73,0x69,0x62,0x6c,0x65,0x41,0x6e,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0x73,0x1,0,0xa,0x45,0x78,0x63,0x65,0x70,0x74,0x69,0x6f,0x6e,0x73,0x10,0x30,0,0x2,0,0x4,0,0x1,0,0x6,0,0x1,0,0x12,0,0x7,0,0x8,0,0,0,0x5,0,0x2,0,0x9,0,0xa,0,0x1,0,0x2e,0,0,0,0x16,0x1,0,0,0x2,0,0,0,0xa,0x2a,0xb7,0,0xd,0x2a,0x2b,0xb5,0,0xf,0xb1,0,0,0,0,0,0xa,0,0x10,0,0x11,0,0x1,0,0x2e,0,0,0,0x15,0,0x3,0,0x1,0,0,0,0x9,0xbb,0,0x2,0x59,0x2a,0xb7,0,0x13,0xb0,0,0,0,0,0,0x1,0,0x14,0,0x15,0,0x2,0,0x2e,0,0,0,0x1b,0,0x2,0,0x2,0,0,0,0xf,0x2a,0xb4,0,0xf,0x2b,0xc0,0,0x18,0xb6,0,0x1c,0xb6,0,0x22,0xb0,0,0,0,0,0,0x2f,0,0,0,0x6,0,0x1,0,0x16,0,0,0,0x12,0,0x23,0,0x24,0,0x2,0,0x2e,0,0,0,0x16,0,0x3,0,0x2,0,0,0,0xa,0xbb,0,0x26,0x59,0x12,0x28,0xb7,0,0x2b,0xbf,0,0,0,0,0,0x30,0,0,0,0x4,0,0x1,0,0x26,0,0x12,0,0x2c,0,0x2d,0,0x2,0,0x2e,0,0,0,0x16,0,0x3,0,0x2,0,0,0,0xa,0xbb,0,0x26,0x59,0x12,0x28,0xb7,0,0x2b,0xbf,0,0,0,0,0,0x30,0,0,0,0x4,0,0x1,0,0x26,0,0,}; 
	
//	std::ifstream f("/Users/zhengxiaolin/Documents/java/java_class_parser/Example.class", std::ios::binary);
//	f.read(the_buf, stat.st_size);
	
//	Mybuf buf(the_buf, stat.st_size);
//	f.read((char *)the_buf, sizeof(the_buf)/sizeof(unsigned char));
	
	Mybuf buf((char *)the_buf, sizeof(the_buf)/sizeof(unsigned char));
	
	std::istream s(&buf);
	
	ClassFile cf;
	s >> cf;
	
}
